import { useUserStore } from '@/stores/user'
import { executeUpsertExercisePlan, queryExercisePlan } from '@/AGC/manager/exercise_plan'
import { queryExerciseByIds, queryExerciseFiltersNotLimit } from '@/AGC/manager/exercise'
import type { UserFiltersI } from '@/types/user'
import { getExerciseDislikeIdsUtil } from '@/AGC/utils/dislike'
import { ExercisePlan } from '@/AGC/model/ExercisePlan'
import type { Exercise } from '@/AGC/model/Exercise'
import { calculateDailyConsume } from '@/utils/calculate_heat'
import type { ExerciseI, ExercisePlanI } from '@/types/exercise'

export const updateSingleExercisePlanUtil = async (
  chooseItem: ExerciseI,
  choosePlan: ExercisePlanI,
) => {
  const exercisePlan = new ExercisePlan()
  // 整合已有数据
  exercisePlan.setId(choosePlan.id)
  exercisePlan.setUser_id(choosePlan.user_id)
  exercisePlan.setDate(choosePlan.date)
  exercisePlan.setAmount(choosePlan.amount)
  // 更新运动名称
  exercisePlan.setExercise_name(chooseItem.name)
  // 更新运动单位
  exercisePlan.setUnit(chooseItem.unit)
  // 更新运动热量
  exercisePlan.setCalories((choosePlan.amount / chooseItem.exercise_amount) * chooseItem.calories)
  // 执行运动计划更新
  await executeUpsertExercisePlan(exercisePlan)
}

/**
 * 获取运动计划列表
 * @param date 日期
 * @returns 运动计划列表
 */
export const getExercisePlanListUtil = async (date: string) => {
  // 1. 根据日期查询运动计划
  let exercisePlanList = await queryExercisePlan(date)

  if (exercisePlanList.length == 0) {
    // 2. 没查到，创建运动计划
    exercisePlanList = await createExercisePlanUtil(date)
  }

  return exercisePlanList.map((item) => {
    return {
      id: item.getId(),
      user_id: item.getUser_id(),
      date: item.getDate(),
      exercise_name: item.getExercise_name(),
      amount: item.getAmount(),
      unit: item.getUnit(),
      calories: item.getCalories(),
    } as ExercisePlanI
  })
}

/**
 * 创建运动计划
 * @param date 日期
 * @returns 运动计划
 */
export const createExercisePlanUtil = async (date: string) => {
  // 1. 查询符合条件的运动筛选条件集合
  const exerciseFilters = await queryExerciseFiltersNotLimit(
    useUserStore().userFilter as UserFiltersI,
  )

  // 2. 查询运动集合
  const exerciseIds = exerciseFilters.map((item) => item.getExercise_id()!)
  const exerciseList = await queryExerciseByIds(exerciseIds)

  // 3. 查询用户不喜欢的运动 ids
  const dislikeIds = await getExerciseDislikeIdsUtil()

  // 4. 过滤用户不喜欢的运动
  const filterExerciseList = exerciseList.filter((item) => !dislikeIds.includes(item.getId()!))

  // 5. 整合运动计划
  const result: ExercisePlan[] = []

  if (filterExerciseList.length >= 3) {
    result.push(...integrationExercisePlan(filterExerciseList, date))
  } else {
    result.push(...integrationExercisePlan(exerciseList, date))
  }

  // 6. 执行运动计划插入
  await executeUpsertExercisePlan(result)

  // 7. 返回运动计划
  return await queryExercisePlan(date)
}

/**
 * 整合运动计划
 * @param list 运动集合
 * @param date 日期
 * @returns 运动计划集合
 */
export const integrationExercisePlan = (list: Exercise[], date: string) => {
  // 1. 计算每日消耗
  const consume = calculateDailyConsume(useUserStore().userFilter as UserFiltersI)

  // 2. 随机分配运动
  let randomList = randomExercise(list, consume)

  if (!randomList) randomList = [list[0], list[1], list[2]]

  // 3. 获取运动量
  const amountStr = (
    consume / randomList.reduce((cal, item) => cal + item.getCalories(), 0)
  ).toString()
  const amount = parseInt(amountStr)

  // 4. 整理数据
  return randomList.map((item) => {
    const exercisePlan = new ExercisePlan()
    exercisePlan.setUser_id(useUserStore().userInfo.id)
    exercisePlan.setDate(date)
    exercisePlan.setExercise_name(item.getName())
    exercisePlan.setAmount(amount * item.getExercise_amount())
    exercisePlan.setUnit(item.getUnit())
    exercisePlan.setCalories(amount * item.getCalories())
    return exercisePlan
  })
}

/**
 * 随机分配运动
 * @param list 运动集合
 * @param consume 每日消耗
 * @returns 运动集合
 */
export const randomExercise = (list: Exercise[], consume: number): Exercise[] | undefined => {
  const result: Exercise[] = []
  let tempList = list

  for (let i = 0; i < 3; i++) {
    result.push(tempList[Math.floor(Math.random() * tempList.length)])
    tempList = tempList.filter((item) => item.getId() != result[i].getId())
  }

  let totalCalories = 0

  result.forEach((item) => {
    totalCalories += item.getCalories()
  })

  if (totalCalories > consume + 20) {
    return randomExercise(list, consume)
  } else {
    return result
  }
}
